﻿using System;
using System.Collections.Generic;

namespace Framework
{
    public abstract class Controller<T> : IController<T> where T : View
    {
        protected T view;
        
        private IEventListener _eventListener;
        private IModuleEventDispatcher _moduleEventDispatcher;
        private Dictionary<Type, IService> _services;
        private Dictionary<Type,IModel> _models;

        private List<int> timerIds;

        protected abstract void Init();

        /// <summary>
        /// 连接上下文
        /// </summary>
        /// <param name="view"></param>
        /// <param name="eventDispatcher"></param>
        public void Connect(T view, IEventListener eventListener, IModuleEventDispatcher moduleEventDispatcher, Dictionary<Type,IService> services, Dictionary<Type, IModel> models)
        {
            this.view = view;
            _eventListener = eventListener;
            _moduleEventDispatcher = moduleEventDispatcher;
            _services = services;
            _models = models;
            
            Init();
        }
        
        protected TService GetService<TService>() where TService : IService
        {
            if (_services.TryGetValue(typeof(TService), out IService service))
            {
                return (TService)service;
            }
            else
            {
                Log.Error("Service "+typeof(TService).Name+"未注册!");
            }

            return default(TService);
        }
        
        protected TModel GetModel<TModel>() where TModel : IModel
        {
            if (_models.TryGetValue(typeof(TModel), out IModel model))
            {
                return (TModel)model;
            }
            else
            {
                Log.Error("Model "+typeof(TModel).Name+"未注册!");
            }

            return default(TModel);
        }
        
        /// <summary>
        /// 倒计时
        /// </summary>
        /// <param name="interval">间隔时间</param>
        /// <param name="stepCallback">每步回调</param>
        /// <param name="finishCallback">结束回调</param>
        /// <param name="finishTime">结束时刻</param>
        /// <returns>Timer Id</returns>
        public int CountDown(float interval, Action<float> stepCallback, Action finishCallback,
            long finishTime = long.MaxValue)
        {
            int id = Timer.Instance.CountDown(interval, stepCallback, finishCallback, finishTime);
            if (timerIds == null)
            {
                timerIds = new List<int>();
            }
            timerIds.Add(id);
            return id;
        }
        
        /// <summary>
        /// 延迟调用
        /// </summary>
        /// <param name="delay">延迟时间</param>
        /// <param name="callback">调用方法</param>
        /// <returns>Timer Id</returns>
        public int DelayCall(float delay, Action callback)
        {
            int id = Timer.Instance.DelayCall(delay, callback);
            if (timerIds == null)
            {
                timerIds = new List<int>();
            }
            timerIds.Add(id);
            return id;
        }

        public virtual void Dispose()
        {
            if(timerIds != null)
            {
                Timer.Instance.RemoveTimers(timerIds);
            }
        }
        

        public void AddListener<T1>(string eventName, Action<T1> handler)
        {
            _eventListener.AddListener(eventName, handler);
        }

        public void AddListener(string eventName, Action handler)
        {
            _eventListener.AddListener(eventName, handler);
        }

        public void AddListener<T1, U>(string eventName, Action<T1, U> handler)
        {
            _eventListener.AddListener(eventName, handler);
        }

        public void AddListener<T1, U, V>(string eventName, Action<T1, U, V> handler)
        {
            _eventListener.AddListener(eventName, handler);
        }

        public void AddListener<T1, U, V, W>(string eventName, Action<T1, U, V, W> handler)
        {
            _eventListener.AddListener(eventName, handler);
        }

        public void Cleanup()
        {
            _eventListener.Cleanup();
        }

        public void RemoveEvents(string eventName)
        {
            _eventListener.RemoveEvents(eventName);
        }

        public void RemoveListener(string eventName, Action handler)
        {
            _eventListener.RemoveListener(eventName, handler);
        }

        public void RemoveListener<T1>(string eventName, Action<T1> handler)
        {
            _eventListener.RemoveListener(eventName, handler);
        }

        public void RemoveListener<T1, U>(string eventName, Action<T1, U> handler)
        {
            _eventListener.RemoveListener(eventName, handler);
        }

        public void RemoveListener<T1, U, V>(string eventName, Action<T1, U, V> handler)
        {
            _eventListener.RemoveListener(eventName, handler);
        }

        public void RemoveListener<T1, U, V, W>(string eventName, Action<T1, U, V, W> handler)
        {
            _eventListener.RemoveListener(eventName, handler);
        }

        public void AddModuleListener<T1>(string eventName, Action<T1> handler)
        {
            _moduleEventDispatcher.AddModuleListener(eventName, handler);
        }

        public void AddModuleListener(string eventName, Action handler)
        {
            _moduleEventDispatcher.AddModuleListener(eventName, handler);
        }

        public void AddModuleListener<T1, U>(string eventName, Action<T1, U> handler)
        {
            _moduleEventDispatcher.AddModuleListener(eventName, handler);
        }

        public void AddModuleListener<T1, U, V>(string eventName, Action<T1, U, V> handler)
        {
            _moduleEventDispatcher.AddModuleListener(eventName, handler);
        }

        public void AddModuleListener<T1, U, V, W>(string eventName, Action<T1, U, V, W> handler)
        {
            _moduleEventDispatcher.AddModuleListener(eventName, handler);
        }

        public void CleanupModuleEvents()
        {
            _moduleEventDispatcher.CleanupModuleEvents();
        }

        public void RemoveModuleEvents(string eventName)
        {
            _moduleEventDispatcher.RemoveModuleEvents(eventName);
        }

        public void RemoveModuleListener(string eventName, Action handler)
        {
            _moduleEventDispatcher.RemoveModuleListener(eventName, handler);
        }

        public void RemoveModuleListener<T1>(string eventName, Action<T1> handler)
        {
            _moduleEventDispatcher.RemoveModuleListener(eventName, handler);
        }

        public void RemoveModuleListener<T1, U>(string eventName, Action<T1, U> handler)
        {
            _moduleEventDispatcher.RemoveModuleListener(eventName, handler);
        }

        public void RemoveModuleListener<T1, U, V>(string eventName, Action<T1, U, V> handler)
        {
            _moduleEventDispatcher.RemoveModuleListener(eventName, handler);
        }

        public void RemoveModuleListener<T1, U, V, W>(string eventName, Action<T1, U, V, W> handler)
        {
            _moduleEventDispatcher.RemoveModuleListener(eventName, handler);
        }

        public void TriggerModuleEvent(string eventName)
        {
            _moduleEventDispatcher.TriggerModuleEvent(eventName);
        }

        public void TriggerModuleEvent<T1>(string eventName, T1 arg1)
        {
            _moduleEventDispatcher.TriggerModuleEvent(eventName, arg1);
        }

        public void TriggerModuleEvent<T1, U>(string eventName, T1 arg1, U arg2)
        {
            _moduleEventDispatcher.TriggerModuleEvent(eventName, arg1, arg2);
        }

        public void TriggerModuleEvent<T1, U, V>(string eventName, T1 arg1, U arg2, V arg3)
        {
            _moduleEventDispatcher.TriggerModuleEvent(eventName, arg1, arg2, arg3);
        }

        public void TriggerModuleEvent<T1, U, V, W>(string eventName, T1 arg1, U arg2, V arg3, W arg4)
        {
            _moduleEventDispatcher.TriggerModuleEvent(eventName, arg1, arg2, arg3, arg4);
        }
    }

}